package es_deusto_engineering_IS_HanoiTower;

import java.util.ArrayList;
import java.util.List;

import es.deusto.ingenieria.is.search.algorithms.Node;
import es.deusto.ingenieria.is.search.algorithms.heuristic.EvaluationFunction;
import es.deusto.ingenieria.is.search.algorithms.heuristic.HeuristicSearchMethod;
import es.deusto.ingenieria.is.search.formulation.Operator;
import es.deusto.ingenieria.is.search.formulation.Problem;
import es.deusto.ingenieria.is.search.formulation.State;

public class HillClimbing extends HeuristicSearchMethod{

	public HillClimbing(EvaluationFunction heuristicF) {
		super(heuristicF);
		heuristicF = new Heuristic1();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public Node search(Problem problem, State initialState) {
		// TODO Auto-generated method stub
		Node initialNode = new Node(initialState);
		Node currentNode;
		currentNode = initialNode;
		boolean local_best = false;
		do
		{
			Node bestSuccesor = this.expand(currentNode, problem);
			if(this.getEvaluationFunction().calculateH(currentNode) > this.getEvaluationFunction().calculateH(bestSuccesor))
			{
				local_best = true;
			}
			else
				currentNode = bestSuccesor;
		}
		while(!local_best);
		
		return currentNode;
	}
	
	//The expand method() only returns the best node taking into account the Heuristic value
	public Node expand(Node node, Problem problem) {
		
		Node bestSuccesor = null;
		Node successorNode = null;
		State currentState = null;
		State successorState = null;

		//If neither node or problem are null
		if (node != null && problem != null) {
			//Get the node's state.
			currentState = node.getState();

			//If the state is not null
			if (currentState != null) {
				int i = 0;
				//Go over the list of problem operators
				for (Operator operator : problem.getOperators()) {
					//Apply the operator to the current state
					successorState = operator.apply(currentState);
					//If the operator has been successfully applied and the resulting successor
					//state hadn't been previously generated nor expanded
					if (successorState != null) {
						i++;
						//make a new node to contain the new successor state
						successorNode = new Node(successorState);
						successorNode.setOperator(operator.getName());
						successorNode.setParent(node);
						successorNode.setDepth(node.getDepth() + 1);
						
						if(i == 0)
						bestSuccesor = successorNode;
					}
				}
			}
		}
		
		return bestSuccesor;
		
	}

}
